//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include "ghost.h"
#include "cservice.h"
#include <aura.h>

EXTERN CServiceCentral * s_pServiceCentral;

STATIC DLinkNode s_hashList[GHOST_HS_SLOTS];
STATIC Aura_Handle    s_hHashListLock = NULL;

ECode Ghost::S_Initialize()
{
    for (Int32 i = 0; i < GHOST_HS_SLOTS; i++) {
        s_hashList[i].Initialize();
    }
    return (ECode)AuraCriticalSection_Create(&s_hHashListLock);
}

void Ghost::S_Destroy()
{
    if (NULL != s_hHashListLock) {
        AuraCriticalSection_Destroy(s_hHashListLock);
        s_hHashListLock = NULL;
    }
    return ;
}

ECode Ghost::S_CreateGhost(
        /* [in] */ GhostFactory * pFactory,
        /* [out] */ Ghost ** ppGhost,
        /* [out] */ Boolean * pbExisted)
{
    return pFactory->CreateGhost(ppGhost, pbExisted);
}

ECode Ghost::S_GetGhost(
        /* [in] */ GhostFactory * pFactory,
        /* [out] */ Ghost ** ppGhost)
{
    return pFactory->GetGhost(ppGhost);
}

ECode Ghost::S_DeleteGhost(
        /* [in] */ GhostFactory * pFactory,
        /* [in] */ Ghost * pGhost)
{
    return pFactory->DeleteGhost(pGhost);
}


// ----------------------------------------------------

ECode GhostFactory::CreateGhost(
        /* [out] */ Ghost ** ppGhost,
        /* [out] */ Boolean * pbExisted)
{
    Ghost * pGhost = NULL;
    ECode ec = NOERROR;
    oid_t oid;

    ObjectType objType = m_pConcreteFactory->GetType();
    Lock(s_hHashListLock);
    ec = s_pServiceCentral->CreateNamedObject(m_name,
                                m_pid, objType, pbExisted, &oid);
    if (FAILED(ec)) {
        goto ErrorExit;
    }
    if (!*pbExisted) {  // new named synchronized object.
        ec = m_pConcreteFactory->CreateGhost(&pGhost, NULL); // addref already.
        if (FAILED(ec)) {
            s_pServiceCentral->DeleteNamedObject(oid);
            goto ErrorExit;
        }
        pGhost->SetOid(oid);
        s_hashList[GHOST_HASHCODE(oid)].InsertLast(pGhost);
        Unlock(s_hHashListLock);

        *ppGhost = pGhost;
        return NOERROR;
    }

    DLinkNode* pHead = &s_hashList[GHOST_HASHCODE(oid)];
    ForEachDLinkNode(Ghost*, pGhost, pHead)
    {
        if (oid == pGhost->GetOid()) {
            pGhost->AddRef();
            Unlock(s_hHashListLock);

            *ppGhost = pGhost;
            return NOERROR;
        }
    }

    Unlock(s_hHashListLock);
    assert(0);
    return E_DOES_NOT_EXIST;

ErrorExit:
    Unlock(s_hHashListLock);
    return ec;
}

ECode GhostFactory::GetGhost(
        /* [out] */ Ghost ** ppGhost)
{
    Ghost    * pGhost = NULL;
    DLinkNode * pHead = NULL;

    assert(NULL != ppGhost);

    pHead = &s_hashList[GHOST_HASHCODE(m_oid)];
    Lock(s_hHashListLock);
    ForEachDLinkNode(Ghost*, pGhost, pHead)
    {
        if (m_oid == pGhost->GetOid()) {
            pGhost->AddRef();
            Unlock(s_hHashListLock);

            *ppGhost = pGhost;
            return NOERROR;
        }
    }
    Unlock(s_hHashListLock);
    return E_DOES_NOT_EXIST;
}

ECode GhostFactory::DeleteGhost(
        /* [out] */ Ghost * pGhost)
{
    ECode ec = NOERROR;

    assert(m_oid == pGhost->GetOid());
    Lock(s_hHashListLock);
    pGhost->Detach();
    ec = s_pServiceCentral->DeleteNamedObject(m_oid);
    Unlock(s_hHashListLock);

    return ec;
}

